import subprocess


def defineAst(filename, types):
    with open(filename+".go", mode='w', encoding="utf-8") as f:
        def p(*args):
            print(*args, file=f)
        p("package main")
        p("type Expr interface {")
        p("accept(visitor AstVisitor) interface{}")
        p("}")
        p()
        p("type AstVisitor interface {")
        for t in types:
            p(f"visit{t}(e *{t}) interface{{}}")
        p("}")
        p()
        for t in types:
            p("type "+ t +" struct {")
            for field in types[t].split(","):
                field = field.strip()
                tp, fieldname = field.split()
                p(fieldname, tp)
            p("}")
            p()
            p(f"func (e *{t}) accept(visitor AstVisitor) interface{{}} {{")
            p(f"return visitor.visit{t}(e)")
            p("}")
            p()
    subprocess.run(['go', 'fmt', filename+'.go'])


def main():
    defineAst("expr", {
        "Binary": "Expr left, Token operator, Expr right",
        "Grouping": "Expr expression",
        "Literal": "interface{} value",
        "Unary": "Token operator, Expr right"
    })


if __name__ == '__main__':
    main()